package com.wzl.kgmusic

import android.media.AudioFormat
import android.media.AudioRecord
import java.io.File
import java.io.FileInputStream
import java.io.FileOutputStream
import java.io.IOException
import kotlin.experimental.and
import kotlin.experimental.or

/**
 * 作者: wzl
 * 时间: 2024/6/25 16:42
 * 作用: 伴奏和录音pcm合并
 */
object PCMFileMerger {
    fun mergePCMFiles(pcmFile1: String?, pcmFile2: String?, outputFile: String?) {
        val sampleRate = 44100 // 根据实际情况调整采样率
        val bufferSize: Int = AudioRecord.getMinBufferSize(
            sampleRate, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT
        )
        try {
            val file1 = FileInputStream(pcmFile1)
            val file2 = FileInputStream(pcmFile2)
            val outFile = FileOutputStream(outputFile)

            val buffer1 = ByteArray(bufferSize)
            val buffer2 = ByteArray(bufferSize)
            val mixBuffer = ShortArray(bufferSize / 2)

            var read1: Int
            var read2: Int

            while (file1.available() > 0 && file2.available() > 0) {
                read1 = file1.read(buffer1)
                read2 = file2.read(buffer2)

                // 将字节数组转换为short数组（每两个字节为一个short）
                bytesToShorts(buffer1, mixBuffer, read1)
                bytesToShorts(buffer2, mixBuffer, read2)

                // 简单的混音处理：取平均值
                for (i in 0 until mixBuffer.size) {
                    mixBuffer[i] = (mixBuffer[i] / 2).toShort() // 这里简单地取两个音频的平均值，可以根据需要实现更复杂的混音算法
                }

                // 将混音后的short数组转换回字节数组
                shortsToBytes(mixBuffer, buffer1, read1)

                // 将混音后的数据写入输出文件
                outFile.write(buffer1, 0, read1)
            }

            file1.close()
            file2.close()
            outFile.close()
        } catch (e: IOException) {
            e.printStackTrace()
        }
    }

    private fun bytesToShorts(input: ByteArray, output: ShortArray, bytesRead: Int) {
        var shortIndex = 0
        var byteIndex = 0
        while (byteIndex < bytesRead) {
            output[shortIndex++] =
                ((input[byteIndex++].toInt() and 0xFF).toShort() or (input[byteIndex++].toInt() shl 8).toShort())
        }
    }

    private fun shortsToBytes(input: ShortArray, output: ByteArray, bytesRead: Int) {
        var shortIndex = 0
        var byteIndex = 0
        while (shortIndex < bytesRead / 2) {
            output[byteIndex++] = (input[shortIndex] and 0xFF).toByte()
            output[byteIndex++] = (input[shortIndex].toInt() shr 8 and 0xFF).toByte()
            shortIndex++
        }
    }
}
